const dayjs = require('dayjs');
/**
 * Store缓存管理辅助类
 * 提供统一的缓存管理接口，用于Store数据的缓存操作
 * 基于MobX响应式设计
 */

import { observable, action, computed } from 'mobx-miniprogram';
import { errorHandler } from './error_handler.js';
import cacheHelper from '../../helpers/cache_helper.js';

// 缓存相关常量
export const CACHE_PREFIX = 'MOBX_STORE_';
export const DEFAULT_EXPIRE_TIME = 30 * 60 * 1000; // 默认30分钟

/**
 * 缓存管理Store
 * 基于MobX响应式设计的缓存管理系统
 */
export const cacheStore = observable({
  // 缓存状态记录
  cacheStatus: {},
  
  // 自动刷新定时器ID
  _refreshTimers: {},
  
  // 缓存统计
  stats: {
    hitCount: 0,
    missCount: 0,
    setCount: 0,
    removeCount: 0,
    lastCleanTime: null
  },
  
  // 初始化
  init: action(function() {
    // 尝试从存储加载缓存状态
    try {
      const statusData = cacheHelper.get(`${CACHE_PREFIX}_STATUS`);
      if (statusData) {
        this.cacheStatus = statusData;
      }
      this._setupAutoCleanup();
    } catch (error) {
      console.error('初始化缓存状态失败:', error);
    }
  }),
  
  /**
   * 设置缓存
   * @param {String} key 缓存键
   * @param {Object} data 要缓存的数据
   * @param {Number} expireTime 过期时间（毫秒）
   * @param {Boolean} autoRefresh 是否自动刷新缓存
   * @param {Function} refreshCallback 刷新回调函数
   * @return {Boolean} 操作结果
   */
  set: action(function(key, data, expireTime = DEFAULT_EXPIRE_TIME, autoRefresh = false, refreshCallback = null) {
    if (!key) return false;
    
    try {
      const cacheKey = `${CACHE_PREFIX}${key}`;
      const now = dayjs().valueOf();
      const expireAt = now + expireTime;
      
      const cacheData = {
        data,
        timestamp: now,
        expireTime: expireAt
      };
      
      // 更新缓存状态
      this.cacheStatus[key] = {
        key,
        hasCache: true,
        createdTime: now,
        expireTime: expireAt,
        size: JSON.stringify(data).length,
        autoRefresh
      };
      
      // 更新统计
      this.stats.setCount++;
      
      // 设置自动刷新
      if (autoRefresh && refreshCallback && typeof refreshCallback === 'function') {
        this._setupRefreshTimer(key, expireTime, refreshCallback);
      }
      
      // 保存缓存状态
      this._saveCacheStatus();
      
      return cacheHelper.set(cacheKey, cacheData);
    } catch (error) {
      console.error(`缓存数据失败 [${key}]:`, error);
      return false;
    }
  }),
  
  /**
   * 获取缓存
   * @param {String} key 缓存键
   * @param {Boolean} ignoreExpire 是否忽略过期检查
   * @return {Object|null} 缓存数据或null
   */
  get: action(function(key, ignoreExpire = false) {
    if (!key) return null;
    
    try {
      const cacheKey = `${CACHE_PREFIX}${key}`;
      const cache = cacheHelper.get(cacheKey);
      
      if (!cache) {
        // 更新缓存状态
        if (this.cacheStatus[key]) {
          this.cacheStatus[key].hasCache = false;
        }
        
        // 更新统计
        this.stats.missCount++;
        
        return null;
      }
      
      // 检查是否过期
      if (!ignoreExpire && cache.expireTime < dayjs().valueOf()) {
        // 已过期，清除缓存
        this.remove(key);
        
        // 更新统计
        this.stats.missCount++;
        
        return null;
      }
      
      // 更新统计
      this.stats.hitCount++;
      
      // 返回缓存数据
      return cache.data;
    } catch (error) {
      console.error(`获取缓存失败 [${key}]:`, error);
      return null;
    }
  }),
  
  /**
   * 检查缓存是否存在且未过期
   * @param {String} key 缓存键
   * @return {Boolean} 是否存在有效缓存
   */
  has: function(key) {
    if (!key) return false;
    
    try {
      const cacheKey = `${CACHE_PREFIX}${key}`;
      const cache = cacheHelper.get(cacheKey);
      
      if (!cache) return false;
      
      // 检查是否过期
      return cache.expireTime >= dayjs().valueOf();
    } catch (error) {
      console.error(`检查缓存失败 [${key}]:`, error);
      return false;
    }
  },
  
  /**
   * 删除缓存
   * @param {String} key 缓存键
   * @return {Boolean} 操作结果
   */
  remove: action(function(key) {
    if (!key) return false;
    
    try {
      const cacheKey = `${CACHE_PREFIX}${key}`;
      
      // 更新缓存状态
      if (this.cacheStatus[key]) {
        delete this.cacheStatus[key];
      }
      
      // 清除刷新定时器
      this._clearRefreshTimer(key);
      
      // 更新统计
      this.stats.removeCount++;
      
      // 保存缓存状态
      this._saveCacheStatus();
      
      return cacheHelper.remove(cacheKey);
    } catch (error) {
      console.error(`删除缓存失败 [${key}]:`, error);
      return false;
    }
  }),
  
  /**
   * 更新缓存过期时间
   * @param {String} key 缓存键
   * @param {Number} expireTime 新的过期时间（毫秒）
   * @return {Boolean} 操作结果
   */
  updateExpireTime: action(function(key, expireTime = DEFAULT_EXPIRE_TIME) {
    if (!key) return false;
    
    try {
      const cacheKey = `${CACHE_PREFIX}${key}`;
      const cache = cacheHelper.get(cacheKey);
      
      if (!cache) return false;
      
      const newExpireTime = dayjs().valueOf() + expireTime;
      
      // 更新缓存数据的过期时间
      cache.expireTime = newExpireTime;
      
      // 更新缓存状态
      if (this.cacheStatus[key]) {
        this.cacheStatus[key].expireTime = newExpireTime;
      }
      
      // 保存缓存状态
      this._saveCacheStatus();
      
      // 保存更新后的缓存
      return cacheHelper.set(cacheKey, cache);
    } catch (error) {
      console.error(`更新缓存过期时间失败 [${key}]:`, error);
      return false;
    }
  }),
  
  /**
   * 清除所有以指定前缀开头的缓存
   * @param {String} prefixKey 前缀键
   * @return {Boolean} 操作结果
   */
  clearByPrefix: action(function(prefixKey) {
    if (!prefixKey) return false;
    
    try {
      // 更新缓存状态
      Object.keys(this.cacheStatus).forEach(key => {
        if (key.startsWith(prefixKey)) {
          delete this.cacheStatus[key];
          this._clearRefreshTimer(key);
        }
      });
      
      // 保存缓存状态
      this._saveCacheStatus();
      
      return cacheHelper.removeAll(`${CACHE_PREFIX}${prefixKey}`);
    } catch (error) {
      console.error(`清除缓存前缀失败 [${prefixKey}]:`, error);
      return false;
    }
  }),
  
  /**
   * 清除所有Store相关缓存
   * @return {Boolean} 操作结果
   */
  clearAll: action(function() {
    try {
      // 清除所有缓存状态
      this.cacheStatus = {};
      
      // 清除所有刷新定时器
      Object.keys(this._refreshTimers).forEach(key => {
        this._clearRefreshTimer(key);
      });
      
      // 保存缓存状态
      this._saveCacheStatus();
      
      // 更新统计
      this.stats.lastCleanTime = dayjs().valueOf();
      
      return cacheHelper.removeAll(CACHE_PREFIX);
    } catch (error) {
      console.error('清除所有缓存失败:', error);
      return false;
    }
  }),
  
  /**
   * 重置缓存统计数据
   */
  resetStats: action(function() {
    this.stats = {
      hitCount: 0,
      missCount: 0,
      setCount: 0,
      removeCount: 0,
      lastCleanTime: this.stats.lastCleanTime
    };
  }),
  
  /**
   * 刷新指定缓存
   * @param {String} key 缓存键
   * @param {Function} refreshCallback 刷新回调函数
   * @return {Promise<Boolean>} 操作结果
   */
  refreshCache: action(async function(key, refreshCallback) {
    if (!key || !refreshCallback || typeof refreshCallback !== 'function') return false;
    
    try {
      // 执行刷新回调获取新数据
      const newData = await refreshCallback();
      
      // 获取原缓存信息
      const cacheStatus = this.cacheStatus[key];
      
      if (!cacheStatus) return false;
      
      // 重新缓存数据
      const expireTime = cacheStatus.expireTime - cacheStatus.createdTime;
      const autoRefresh = cacheStatus.autoRefresh;
      
      return this.set(key, newData, expireTime, autoRefresh, refreshCallback);
    } catch (error) {
      console.error(`刷新缓存失败 [${key}]:`, error);
      return false;
    }
  }),
  
  /**
   * 获取缓存状态
   * @param {String} key 缓存键
   * @return {Object|null} 缓存状态
   */
  getCacheStatus: function(key) {
    return this.cacheStatus[key] || null;
  },
  
  /**
   * 设置自动刷新定时器
   * @private
   */
  _setupRefreshTimer: function(key, expireTime, refreshCallback) {
    // 清除已有定时器
    this._clearRefreshTimer(key);
    
    // 设置新定时器，在过期前10秒刷新
    const refreshTime = Math.max(expireTime - 10000, expireTime / 2);
    
    this._refreshTimers[key] = setTimeout(() => {
      this.refreshCache(key, refreshCallback).catch(error => {
        console.error(`自动刷新缓存失败 [${key}]:`, error);
      });
    }, refreshTime);
  },
  
  /**
   * 清除刷新定时器
   * @private
   */
  _clearRefreshTimer: function(key) {
    if (this._refreshTimers[key]) {
      clearTimeout(this._refreshTimers[key]);
      delete this._refreshTimers[key];
    }
  },
  
  /**
   * 保存缓存状态
   * @private
   */
  _saveCacheStatus: function() {
    try {
      cacheHelper.set(`${CACHE_PREFIX}_STATUS`, this.cacheStatus);
    } catch (error) {
      console.error('保存缓存状态失败:', error);
    }
  },
  
  /**
   * 设置自动清理定时器
   * @private
   */
  _setupAutoCleanup: function() {
    // 每小时运行一次清理过期缓存
    setInterval(() => {
      this._cleanupExpiredCache();
    }, 60 * 60 * 1000);
  },
  
  /**
   * 清理过期缓存
   * @private
   */
  _cleanupExpiredCache: action(function() {
    const now = dayjs().valueOf();
    let cleanCount = 0;
    
    // 遍历缓存状态找出过期缓存
    Object.keys(this.cacheStatus).forEach(key => {
      const status = this.cacheStatus[key];
      if (status.expireTime < now) {
        // 移除过期缓存
        this.remove(key);
        cleanCount++;
      }
    });
    
    if (cleanCount > 0) {
      console.log(`自动清理了${cleanCount}个过期缓存`);
    }
    
    // 更新最后清理时间
    this.stats.lastCleanTime = now;
  }),
  
  // 计算属性
  
  /**
   * 获取缓存命中率
   */
  get hitRate() {
    const total = this.stats.hitCount + this.stats.missCount;
    if (total === 0) return 0;
    return (this.stats.hitCount / total * 100).toFixed(2);
  },
  
  /**
   * 获取总缓存数量
   */
  get totalCacheCount() {
    return Object.keys(this.cacheStatus).length;
  },
  
  /**
   * 获取总缓存大小(KB)
   */
  get totalCacheSize() {
    let totalSize = 0;
    Object.values(this.cacheStatus).forEach(status => {
      totalSize += status.size || 0;
    });
    return (totalSize / 1024).toFixed(2);
  },
  
  /**
   * 获取近期过期的缓存
   * (5分钟内过期)
   */
  get soonExpiredCaches() {
    const now = dayjs().valueOf();
    const expireThreshold = now + 5 * 60 * 1000;
    
    return Object.keys(this.cacheStatus).filter(key => {
      const status = this.cacheStatus[key];
      return status.expireTime > now && status.expireTime < expireThreshold;
    });
  }
});

/**
 * 兼容旧版API的静态类
 * 提供与旧版API兼容的方法，内部转发到cacheStore
 */
export class Cache {
  static set(key, data, expireTime = DEFAULT_EXPIRE_TIME) {
    return cacheStore.set(key, data, expireTime);
  }
  
  static get(key, ignoreExpire = false) {
    return cacheStore.get(key, ignoreExpire);
  }
  
  static has(key) {
    return cacheStore.has(key);
  }
  
  static remove(key) {
    return cacheStore.remove(key);
  }
  
  static isExpired(key) {
    const status = cacheStore.getCacheStatus(key);
    if (!status) return true;
    return status.expireTime < dayjs().valueOf();
  }
  
  static updateExpireTime(key, expireTime = DEFAULT_EXPIRE_TIME) {
    return cacheStore.updateExpireTime(key, expireTime);
  }
  
  static clearByPrefix(prefixKey) {
    return cacheStore.clearByPrefix(prefixKey);
  }
  
  static clearAll() {
    return cacheStore.clearAll();
  }
  
  static getCreateTimeFormatted(key, format = 'YYYY-MM-DD HH:mm:ss') {
    const status = cacheStore.getCacheStatus(key);
    if (!status || !status.createdTime) return '';
    return dayjs(status.createdTime).format(format);
  }
  
  static getExpireTimeFormatted(key, format = 'YYYY-MM-DD HH:mm:ss') {
    const status = cacheStore.getCacheStatus(key);
    if (!status || !status.expireTime) return '';
    return dayjs(status.expireTime).format(format);
  }
  
  static getTimeLeft(key) {
    const status = cacheStore.getCacheStatus(key);
    if (!status || !status.expireTime) return 0;
    
    const timeLeft = status.expireTime - dayjs().valueOf();
    return timeLeft > 0 ? timeLeft : 0;
  }
} 